package com.zhuhjay.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhuhjay.common.exception.CustomException;
import com.zhuhjay.system.domain.entity.Menu;
import com.zhuhjay.system.mapper.MenuMapper;
import com.zhuhjay.system.service.IMenuService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zhuhjay
 * @since 2022-03-20
 */
@Service
@Transactional(rollbackFor = CustomException.class)
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {

    @Override
    public List<Menu> getMenus() {
        // 查询所有的菜单并按照order字段进行排序
        QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
        // 找到所有的父菜单并排序
        queryWrapper.eq("parent", "-1").orderByAsc("orderNum");
        // 获取所有菜单并进行处理
        return menusHandler(baseMapper.selectList(queryWrapper));
    }

    @Override
    public void saveMenu(Menu menu) {
        // 求出当前待添加菜单的order序列
        QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent", menu.getParent());
        Long count = baseMapper.selectCount(queryWrapper);
        menu.setOrderNum(count.intValue() + 1);
        int insert = baseMapper.insert(menu);
        if( insert != 1 ) {
            throw new CustomException("菜单创建失败");
        }
    }

    @Override
    public void updateMenu(Menu menu) {
        Menu oldMenu = baseMapper.selectById(menu.getId());
        // 判断是否进行菜单序号的切换(使用插入式修改)
        if( isUpdateOrder(oldMenu, menu) ){
            reorderMenu(oldMenu, menu);
        }
        if( baseMapper.updateById(menu) != 1 ){
            throw new CustomException("菜单序列修改失败");
        }
    }

    private boolean isUpdateOrder(Menu oldMenu, Menu newMenu) {
        return !oldMenu.getOrderNum().equals(newMenu.getOrderNum());
    }

    private void reorderMenu(Menu oldMenu, Menu newMenu) {
        QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
        // 获取同级菜单切序列在新旧序列中间
        queryWrapper
                .eq("parent", newMenu.getParent())
                .between("orderNum", oldMenu.getOrderNum(), newMenu.getOrderNum())
                .orderByAsc("orderNum");
        List<Menu> menus = baseMapper.selectList(queryWrapper);
        int tempOrder;
        // 进行序列重排(攘除正在进行修改信息的菜单)
        // 1 2 3 4 5 6 情况
        //   ^_____|
        if( oldMenu.getOrderNum() > newMenu.getOrderNum() ){
            tempOrder = newMenu.getOrderNum();
            Menu updateOrderMenu = new Menu();
            for (int i = 0; i < menus.size() - 1; i++) {
                updateOrderMenu.setOrderNum(++tempOrder);
                updateOrderMenu.setId(menus.get(i).getId());
                if( baseMapper.updateById(updateOrderMenu) != 1 ){
                    throw new CustomException("菜单序列修改失败");
                }
            }
        }
        // 1 2 3 4 5 6 情况
        //   |_____^
        else {
            tempOrder = oldMenu.getOrderNum();
            Menu updateOrderMenu = new Menu();
            for (int i = 1; i < menus.size(); i++) {
                updateOrderMenu.setOrderNum(tempOrder++);
                updateOrderMenu.setId(menus.get(i).getId());
                if( baseMapper.updateById(updateOrderMenu) != 1 ){
                    throw new CustomException("菜单序列修改失败");
                }
            }
        }
    }

    /**
     * 递归: 将菜单分类并整理为一个数组对象
     */
    private List<Menu> menusHandler(List<Menu> menus){
        menus.forEach(menu -> {
            QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("parent", menu.getId()).orderByAsc("orderNum");
            List<Menu> children = baseMapper.selectList(queryWrapper);
            if( !children.isEmpty() ){
                // 使用递归进行多级菜单的排序和获取
                menu.setChildren(menusHandler(children));
            }
        });
        return menus;
    }
}
